import * as XLSX from 'xlsx'

/**
 * Excel导出配置接口
 */
export interface ExportConfig {
  /** 文件名（不含扩展名） */
  fileName: string
  /** 表头配置 */
  headers: ExportHeader[]
  /** 数据数组 */
  data: any[]
  /** 工作表名称 */
  sheetName?: string
}

/**
 * 表头配置接口
 */
export interface ExportHeader {
  /** 表头显示名称 */
  label: string
  /** 对应数据字段名 */
  prop: string
  /** 数据格式化函数 */
  formatter?: (value: any, row?: any) => string | number
}

/**
 * 导出Excel文件
 * @param config 导出配置
 */
export function exportToExcel(config: ExportConfig): void {
  const { fileName, headers, data, sheetName = 'Sheet1' } = config

  // 构建表头行
  const headerRow = headers.map(h => h.label)

  // 构建数据行
  const dataRows = data.map(row => {
    return headers.map(header => {
      const value = getNestedValue(row, header.prop)

      // 如果有格式化函数，使用格式化函数
      if (header.formatter) {
        return header.formatter(value, row)
      }

      // 否则返回原值
      return value ?? ''
    })
  })

  // 合并表头和数据
  const sheetData = [headerRow, ...dataRows]

  // 创建工作表
  const worksheet = XLSX.utils.aoa_to_sheet(sheetData)

  // 设置列宽（可选）
  const colWidths = headers.map(header => {
    // 根据表头长度和内容长度设置列宽
    const headerLength = header.label.length
    const maxContentLength = Math.max(
      ...dataRows.map(row => {
        const cellIndex = headers.indexOf(header)
        const cellValue = String(row[cellIndex] ?? '')
        return cellValue.length
      })
    )
    const width = Math.max(headerLength, maxContentLength, 10)
    return { wch: Math.min(width, 50) } // 最大宽度50
  })
  worksheet['!cols'] = colWidths

  // 创建工作簿
  const workbook = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(workbook, worksheet, sheetName)

  // 生成文件名（添加时间戳）
  const timestamp = formatDateTime(new Date())
  const fullFileName = `${fileName}_${timestamp}.xlsx`

  // 导出文件
  XLSX.writeFile(workbook, fullFileName)
}

/**
 * 获取嵌套对象的值
 * @param obj 对象
 * @param path 属性路径，支持 'user.name' 格式
 */
function getNestedValue(obj: any, path: string): any {
  if (!obj || !path) return undefined

  const keys = path.split('.')
  let value = obj

  for (const key of keys) {
    if (value === null || value === undefined) {
      return undefined
    }
    value = value[key]
  }

  return value
}

/**
 * 格式化日期时间为文件名格式
 * @param date 日期对象
 * @returns YYYYMMDD_HHmmss 格式的字符串
 */
function formatDateTime(date: Date): string {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')

  return `${year}${month}${day}_${hours}${minutes}${seconds}`
}

/**
 * 格式化金额（韩元）
 * @param amount 金额
 * @returns 格式化后的金额字符串
 */
export function formatAmount(amount: number | string): string {
  const num = typeof amount === 'string' ? parseFloat(amount) : amount
  if (isNaN(num)) return '0'
  return num.toLocaleString('ko-KR')
}

/**
 * 格式化NEAR数量
 * @param amount NEAR数量
 * @returns 格式化后的NEAR字符串
 */
export function formatNearAmount(amount: number | string): string {
  const num = typeof amount === 'string' ? parseFloat(amount) : amount
  if (isNaN(num)) return '0'
  return num.toFixed(6)
}

/**
 * 格式化日期时间
 * @param dateString 日期字符串
 * @returns 格式化后的日期时间字符串
 */
export function formatDateTimeString(dateString: string | Date): string {
  if (!dateString) return ''

  const date = typeof dateString === 'string' ? new Date(dateString) : dateString

  if (isNaN(date.getTime())) return ''

  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

/**
 * 格式化百分比
 * @param value 数值
 * @param decimals 小数位数
 * @returns 格式化后的百分比字符串
 */
export function formatPercentage(value: number | string, decimals: number = 2): string {
  const num = typeof value === 'string' ? parseFloat(value) : value
  if (isNaN(num)) return '0%'
  return `${(num * 100).toFixed(decimals)}%`
}
